跨域的理解

跨域,顾名思义,即为请求了不同域的资源。
了解跨域这件事,我们先看看导致会存在跨域问题的根源:浏览器的同源策略
浏览器的同源策略又是什么鬼? 好像了解一点,但是又说不清楚。这次我们就来详细探索一下。

声明一下,本文是参考众多其他有关跨域文章结合自己技术认识所做的记录,请与
浏览器同源政策及其规避方法参考着看更加合适。

同源策略:(the same-origin policy)

MDN
维基百科
In computing, the same-origin policy is an important concept in the web application security model. Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. An origin is defined as a combination of URI scheme, host name, and port number. This policy prevents a malicious script on one page from obtaining access to sensitive data on another web page through that page's Document Object Model.
简单翻译一下:
在web应用安全模型中,同源策略是一个重要的概念。在该策略下,仅俩个页面有相同的源, web浏览器才允许包含在第一个页面中的脚本访问第二个web页面的数据。源被定义为 URI协议,主机名,端口号的组合。该策略阻止了一个页面的恶意脚本通过文档对象模型(DOM)获得其他的web页面的敏感数据.
那为什么会有同源策略呢,可以参考一下,CSRF这篇文章谈到CSRF这种情况。
那哪些数据会被限制呢?
敏感数据一般指的是浏览器中的Cookies, SessionStorage, LocalStorage, IndexedDB数据, CacheStorage, ApplicationCache...;

同源策略限制范围

阮一峰老师还对同源策略对于非同源,限制的行为做了归纳:

“
如果非同源,共有三种行为受到限制。
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
 虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。下面,我将详细介绍,如何规避上面三种限制。
”

以下对阮老师总结的方法进行测试

Cookies

浏览器允许通过设置document.domain共享 Cookie。
document.domain的写操作是有要求的。只能写入基础域名和当前域名,其他域名是无法写入的,所以domain这种方式只能在亲子域名之间共享cookies
// 由于还没有相关资源(三级域名资源,域名资源),没有做验证

iframe

页面1 localhost:8080的页面,包含一个页面2 (iframe = http://localhost:8081);
页面2中访问window.parent.document报跨源错误
在页面2中window.parent可以访问,但是在iframe中访问获取到的window.parent对象中属性缺少了有关DOM的部分,而直接在页面1中查看window对象,可以看到document属性对象,而使用夸源window.parent无法获取document属性对象
  • 片段识别符(fragment identifier)
  • window.name
  • 跨文档通信API(Cross-document messaging)
片段识别符 fragment identifier

所以这种方式,无论是否夸源,父窗口可以通过更改子窗口的iframe的src中的hash值来传递数据给子窗口;
但是 在存在跨源的情况下,子窗口获取parent.location.href(可写不可读)读操作会报跨源错误,所以子窗口课件写入url的方式传递数据给父窗口。
片段识别符方式可以父传子,子传父

window.name

document.getElementById('iframe').contentWindow.name
访问出错,所以无法跨域

window.postMessage

页面1 调用iframe的iframe.contentWindow.postMessage(data,"http://localhost:8081")
页面2 调用window的 window.parent.postMessage(data,'http://localhost:8080')

AJAX (最常见到的情况)

“
同源政策规定,AJAX请求只能发给同源的网址,否则就报错。
除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。

JSONP
WebSocket
CORS
”
JSONP
// 客户端(浏览器页面)
function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');//需要指定回调函数名
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};


//服务端
foo({
  "ip": "8.8.8.8"
});
CORS

CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。
请参考 阮老师的跨域资源共享 CORS 详解


言月
1.8k 声望490 粉丝

从有技术广度到技术深度的转变,这样才能被自己迷恋